<?php
/**
 * This file is part of the Jindai.
 * @copyright Copyright (c) 2019 All Rights Reserved.
 * @author jindai <jindai0305@gmail.com>
 */

namespace App\Repositories;

use App\Exceptions\MusicFailedException;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Http\Request;

/**
 * Class MusicRepository
 * @package App\Repositories
 */
class MusicRepository
{
    protected $client;

//    const BASE_SEARCH_URL = 'http://jadeite.migu.cn:7090/music_search/v2';
    const BASE_SEARCH_URL = 'https://pd.musicapp.migu.cn/MIGUM3.0/v1.0/content/search_all.do';

    //app.pd.nf.migu.cn/MIGUM2.0/v1.0/content/sub/listenSong.do?toneFlag=HQ&netType=00&userId=15548614588710179085069&ua=Android_migu&version=5.1&copyrightId=0&contentId={contentId}&resourceType=2&channel=0
    const MUSIC_PLAYER_URL = '';

    protected $meta = [
        'total' => 0,
        'page' => 1,
        'limit' => 20,
        'point' => 0
    ];

    const NORMAL_HEADERS = [
        'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        'Host' => 'pd.musicapp.migu.cn',
    ];

    public function __construct(\App\Support\Request $request)
    {
        $this->client = $request;
    }

    /**
     * @param Request $request
     * @return mixed|\Psr\Http\Message\ResponseInterface|string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function search(Request $request)
    {
        list($page, $limit) = $this->getPageParams($request);

//        $response = $this->request('GET', self::BASE_SEARCH_URL . '/search/searchAll', [
//            'feature' => 1111000000,
//            'isCopyright' => 1,
//            'isCorrect' => 1,
//            'sort' => 0,
//            'uiVersion' => 'I_music_3.0.2',
//            'pageIndex' => $page,
//            'pageSize' => $limit,
//            'text' => $request->query('q', ''),
//            'searchSwitch' => json_encode([
//                "song" => 1,
//                "album" => 0,
//                "singer" => 0,
//                "tagSong" => 0,
//                "mvSong" => 0,
//                "songlist" => 0,
//                "bestShow" => 0,
//                "lyricSong" => 0,
//                "concert" => 0,
//                "periodical" => 0,
//                "ticket" => 0,
//                "bit24" => 0,
//                "verticalVideoTone" => 0,
//            ])
//        ], config('website.music.search-headers'));
        $response = $this->request('GET', self::BASE_SEARCH_URL, [
            'ua' => 'Android_migu',
            'version' => '5.0.1',
            'text' => $request->query('q', ''),
            'pageNo' => $page,
            'pageSize' => $limit,
            'searchSwitch' => json_encode([
                "song" => 1,
                "album" => 0,
                "singer" => 0,
                "tagSong" => 0,
                "mvSong" => 0,
                "songlist" => 0,
                "bestShow" => 0,
            ])
        ], self::NORMAL_HEADERS);


        if (!isset($response['songResultData']) || !isset($response['songResultData']['totalCount'])) {
            return [];
        }

        $this->setMeta($request, ['total' => $response['songResultData']['totalCount']]);

        return $response['songResultData']['result'];
    }

    /**
     * @return array
     */
    public function getMeta()
    {
        return $this->meta;
    }

    /**
     * @param $request
     * @param $append
     */
    protected function setMeta($request, $append)
    {
        list($page, $limit) = $this->getPageParams($request);

        $this->meta = array_merge($this->meta, [
            'page' => $page,
            'limit' => $limit
        ], $append);
    }

    /**
     * @param Request $request
     * @return array
     */
    protected function getPageParams(Request $request)
    {
        $page = max(1, $request->get('page', 1));
        $limit = min(20, $request->get('limit', 20));

        return [$page, $limit];
    }

    /**
     * @param $method
     * @param $url
     * @param $params
     * @param $headers
     * @return mixed|\Psr\Http\Message\ResponseInterface|string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected function request($method, $url, $params, $headers)
    {
        try {
            $response = $this->client->guzzleHttpRequest($method, $url, $params, [
                'headers' => $headers
            ]);
            $result = json_decode((string)$response->getBody()->getContents(), true);
            if ($result['code'] !== '000000') {
                throw new MusicFailedException([], '服务不可用', '403');
            }
            return $result;
        } catch (\Exception $exception) {
            if ($exception instanceof MusicFailedException) {
                throw $exception;
            }

            $this->handlerException($exception);
        }
    }

    /**
     * @param \Exception $exception
     */
    protected function handlerException(\Exception $exception)
    {
        $status_code = $exception->getCode() ?: 403;
        $response = [
            'error' => 'invalid_credentials',
            'error_description' => 'The user credentials were incorrect.',
            'message' => '签名失效.'
        ];

        if ($exception instanceof ClientException) {
            if ($exception->hasResponse()) {
                $response = json_decode($exception->getResponse()->getBody()->getContents(), true);
            }
        }

        if (count($response) && $status_code === 403) {
            $message = current($response);
        } else {
            $message = $response ? end($response) : 'server error';
        }

        throw new MusicFailedException($response, $message, $status_code);
    }
}
